#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include "imbus_internal.h"
#include "im_hash.h"
#include "im_quark.h"

/******** defines ********/
#define	IM_QUARK_BLOCK_SIZE         (512)

/******** variables *********/
static IMHashTable   *im_quark_ht       = 0;
static IMChar       **im_quarks         = 0;
static IMQuark        im_quark_seq_id   = 0;

/******** functions *********/
static inline IMQuark
im_quark_new (IMChar *string)
{
    IMQuark quark;
  
    if (im_quark_seq_id % IM_QUARK_BLOCK_SIZE == 0)
        im_quarks = im_renew (IMChar*, im_quarks, im_quark_seq_id + IM_QUARK_BLOCK_SIZE);

    if (!im_quark_ht) {
        _im_assert (im_quark_seq_id == 0);
        im_quark_ht = im_hash_table_new (im_str_hash, im_str_equal);
        im_quarks[im_quark_seq_id++] = 0;
    }

    quark = im_quark_seq_id++;
    im_quarks[quark] = string;
    im_hash_table_insert (im_quark_ht, string, IM_UINT_TO_POINTER (quark));
 
    return quark;
}
static inline IMQuark
im_quark_from_string_internal (const IMChar *string, IMBool duplicate)
{
    IMQuark quark = 0;

    if (im_quark_ht)
        quark = IM_POINTER_TO_UINT (im_hash_table_lookup (im_quark_ht, string));

    if (!quark)
        quark = im_quark_new (duplicate ? strdup (string) : (IMChar *)string);
 
    return quark;
}
IMQuark
im_quark_try_string (const IMChar *string)
{
    IMQuark quark = 0;

    _im_return_val_if_fail (string != 0, 0);

    if (im_quark_ht)
        quark = IM_POINTER_TO_UINT (im_hash_table_lookup (im_quark_ht, string));

    return quark;
}
IMQuark
im_quark_from_static_string (const IMChar *string)
{
    IMQuark quark;

    _im_return_val_if_fail (string != 0, 0);

    quark = im_quark_from_string_internal (string, FALSE);

    return quark;
}
IMQuark
im_quark_from_string (const IMChar *string)
{
    IMQuark quark;

    _im_return_val_if_fail (string != 0, 0);

    quark = im_quark_from_string_internal (string, TRUE);

    return quark;
}
const IMChar*
im_quark_to_string (IMQuark quark)
{
    IMChar* result = 0;

    if (quark < im_quark_seq_id)
        result = im_quarks[quark];

    return result;
}
const IMChar*
im_intern_string (const IMChar *string)
{
    const IMChar *result;
    IMQuark quark;

    if (!string)
        return 0;

    quark = im_quark_from_string_internal (string, TRUE);
    result = im_quarks[quark];

    return result;
}
const IMChar*
im_intern_static_string (const IMChar *string)
{
    IMQuark quark;
    const IMChar *result;

    if (!string)
        return 0;

    quark = im_quark_from_string_internal (string, FALSE);
    result = im_quarks[quark];

    return result;
}

/*
vi:ts=4:nowrap:ai:expandtab
*/
